package com.thz.system.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 异步任务配置
 * 为视频转换等耗时操作提供独立的线程池
 * 
 * @author THZ
 * @date 2025
 */
@Slf4j
@Configuration
@EnableAsync
public class AsyncTaskConfig {
    
    @Autowired
    private MattingProperties mattingProperties;
    
    /**
     * 视频转换专用线程池
     * 优化配置：避免过度并行导致CPU资源竞争
     * 
     * 【关键优化】：
     * 1. FFmpeg是CPU密集型任务，过多线程会导致上下文切换开销
     * 2. 单个FFmpeg进程已经使用多核（通过-threads参数），不需要太多并发
     * 3. 减少线程数可以让每个任务获得更多CPU时间片，反而更快
     */
    @Bean(name = "videoConversionExecutor")
    public Executor videoConversionExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 获取CPU核心数
        int cpuCores = Runtime.getRuntime().availableProcessors();
        
        // 核心线程数：2（优化后）
        // 原因：FFmpeg本身会使用多核，2个并发任务已经足够充分利用CPU
        // 过多并发会导致资源竞争和上下文切换
        executor.setCorePoolSize(2);
        
        // 最大线程数：4（优化后）
        // 原因：即使高峰期，4个并发FFmpeg任务已经是极限
        // 更多并发只会降低每个任务的速度
        executor.setMaxPoolSize(4);
        
        // 队列容量：100个任务
        // 当所有核心线程都在执行任务时，新任务会进入队列等待
        executor.setQueueCapacity(100);
        
        // 线程空闲时间：60秒
        // 非核心线程空闲60秒后会被回收
        executor.setKeepAliveSeconds(60);
        
        // 线程名称前缀
        executor.setThreadNamePrefix("video-conversion-");
        
        // 拒绝策略：由调用者线程执行
        // 当队列满且达到最大线程数时，由提交任务的线程自己执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 等待所有任务完成后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        
        // 最多等待60秒
        executor.setAwaitTerminationSeconds(60);
        
        // 初始化
        executor.initialize();
        
        log.info("视频转换线程池初始化完成（优化配置） - CPU核心数: {}, 核心线程数: 2, 最大线程数: 4, 队列容量: 100", 
                cpuCores);
        log.info("【性能优化】减少并发数以避免CPU资源竞争，单个任务将获得更多CPU时间");
        
        return executor;
    }
    
    /**
     * 文件上传/下载专用线程池
     * 优化配置：本地文件I/O不需要太多线程
     */
    @Bean(name = "fileIoExecutor")
    public Executor fileIoExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 获取CPU核心数
        int cpuCores = Runtime.getRuntime().availableProcessors();
        
        // 核心线程数：4（优化后）
        // 原因：本地文件I/O受磁盘速度限制，不需要太多线程
        executor.setCorePoolSize(4);
        
        // 最大线程数：8（优化后）
        // 原因：即使是网络I/O，8个并发也足够了
        executor.setMaxPoolSize(8);
        
        // 队列容量：200个任务
        executor.setQueueCapacity(200);
        
        // 线程空闲时间：60秒
        executor.setKeepAliveSeconds(60);
        
        // 线程名称前缀
        executor.setThreadNamePrefix("file-io-");
        
        // 拒绝策略：由调用者线程执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 等待所有任务完成后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        
        // 最多等待60秒
        executor.setAwaitTerminationSeconds(60);
        
        // 初始化
        executor.initialize();
        
        log.info("文件I/O线程池初始化完成（优化配置） - CPU核心数: {}, 核心线程数: 4, 最大线程数: 8, 队列容量: 200", 
                cpuCores);
        
        return executor;
    }
    
    /**
     * 图片抠图专用线程池
     * CPU密集型任务（rembg AI推理），并发数受限于CPU和内存
     */
    @Bean(name = "imageMattingExecutor")
    public Executor imageMattingExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        
        // 获取CPU核心数
        int cpuCores = Runtime.getRuntime().availableProcessors();
        
        // 从配置读取，默认针对2核4G为单线程
        executor.setCorePoolSize(mattingProperties.getExecutorCorePoolSize());
        
        // 最大线程数
        executor.setMaxPoolSize(mattingProperties.getExecutorMaxPoolSize());
        
        // 队列容量
        executor.setQueueCapacity(mattingProperties.getExecutorQueueCapacity());
        
        // 线程空闲时间：120秒
        // 由于启动AI模型有开销，保持线程存活时间长一些
        executor.setKeepAliveSeconds(120);
        
        // 线程名称前缀
        executor.setThreadNamePrefix("image-matting-");
        
        // 拒绝策略：由调用者线程执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        
        // 等待所有任务完成后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        
        // 最多等待180秒（抠图可能需要更长时间）
        executor.setAwaitTerminationSeconds(180);
        
        // 初始化
        executor.initialize();
        
        log.info("图片抠图线程池初始化 - 核心线程数: {}, 最大线程数: {}, 队列容量: {}, CPU核心数: {}", 
                mattingProperties.getExecutorCorePoolSize(),
                mattingProperties.getExecutorMaxPoolSize(),
                mattingProperties.getExecutorQueueCapacity(),
                cpuCores);
        
        return executor;
    }
}

